package com.easylinkin.linkappapi.inspection.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.config.entity.Config;
import com.easylinkin.linkappapi.config.service.ConfigService;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.service.DevicePositionService;
import com.easylinkin.linkappapi.device.service.DeviceService;
import com.easylinkin.linkappapi.devicetype.entity.DeviceType;
import com.easylinkin.linkappapi.devicetype.service.DeviceTypeService;
import com.easylinkin.linkappapi.deviceunit.entity.DeviceUnit;
import com.easylinkin.linkappapi.deviceunit.service.DeviceUnitService;
import com.easylinkin.linkappapi.inspection.dto.ElectricBoxDTO;
import com.easylinkin.linkappapi.inspection.entity.ElectricBox;
import com.easylinkin.linkappapi.inspection.mapper.ElectricBoxMapper;
import com.easylinkin.linkappapi.inspection.service.ElectricBoxService;
import com.easylinkin.linkappapi.inspection.service.ElectricStatisticsService;
import com.easylinkin.linkappapi.messagecenter.entity.MessageCenter;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappPrivilege;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.mapper.LinkappUserMapper;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 配电箱表 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2022-04-13
 */
@Service
public class ElectricBoxServiceImpl extends ServiceImpl<ElectricBoxMapper, ElectricBox> implements
    ElectricBoxService {

  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;

  @Autowired
  private ElectricStatisticsService electricStatisticsService;

  @Autowired
  private LinkappUserMapper linkappUserMapper;

  @Autowired
  private ConfigService configService;

  @Autowired
  private DeviceTypeService deviceTypeService;

  @Autowired
  private DeviceUnitService deviceUnitService;

  @Autowired
  private DeviceService deviceService;

  @Autowired
  private DevicePositionService devicePositionService;

  @Value("${inspection.url}")
  public String qrCodeUrl;

  /**
   * 增加
   * @param electricBox
   */
  @Override
  public void insert(ElectricBox electricBox) {
    /**
     * 验证重复
     */
    this.checkExist(electricBox);
    /**
     * 校验电气火灾设备是否重复绑定
     */
    this.checkMonitorDevice(electricBox);
    //设置基本属性
    this.setBase(electricBox);
    this.save(electricBox);
    //todo 生成二维码
    //更新今天的统计
    electricStatisticsService.countToday();
  }

  /**
   * 根据id编辑
   * @param electricBox
   */
  @Override
  public void updateOne(ElectricBox electricBox) {
    /**
     * 验证重复
     */
    this.checkExist(electricBox);
    /**
     * 校验电气火灾设备是否重复绑定
     */
    this.checkMonitorDevice(electricBox);
    //设置基本属性
    this.setBase(electricBox);
    this.updateById(electricBox);
    //如果电气火灾设备为空，则将原来的电气火灾监控设备设置成空
    if(StringUtils.isBlank(electricBox.getMonitorDeviceCode())){
      baseMapper.removeMonitorDevice(electricBox);
    }
    //todo 生成二维码
  }

  /**
   * @Description: 删除配电箱（包含批量删除）
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public void delBatch(Set<String> ids) {
    //逻辑删除
    UpdateWrapper<ElectricBox> updateWrapper = new UpdateWrapper<>();
    updateWrapper.in("id",ids)
        .set("is_delete_",1)
        .set("modify_id_",linkappUserContextProducer.getCurrent().getId())
        .set("modify_time_",new Date());
    baseMapper.update(null,updateWrapper);
    //删除已经存在的打点信息
    clearDevicePosition(ids);
    //更新今天的统计
    electricStatisticsService.countToday();
  }

  private void clearDevicePosition(Set<String> ids) {
    QueryWrapper<ElectricBox> queryWrapper = new QueryWrapper<>();
    queryWrapper.in("id", ids);
    List<ElectricBox> electricBoxes = baseMapper.selectList(queryWrapper);
    if(CollectionUtil.isNotEmpty(electricBoxes)){
      List<String> codes = electricBoxes.stream().map(ElectricBox::getCode)
          .collect(Collectors.toList());
      devicePositionService.clearDevicePosition(codes);
    }
  }

  /**
   * @Description: 查询电工
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public List<LinkappUser> queryLeads() {
    //查询具备巡检填报的用户
    LinkappPrivilege linkappPrivilege = new LinkappPrivilege();
    linkappPrivilege.setCode("electricCheck");
    linkappPrivilege.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    linkappPrivilege.setType(2);
    List<LinkappUser> users = linkappUserMapper.findByCode(linkappPrivilege);
    return users;
  }

  @Override
  public IPage<ElectricBox> queryListByPage(RequestModel<ElectricBox> requestModel) {
    Page page = requestModel.getPage();
    ElectricBox electricBox = requestModel.getCustomQueryParams();
    electricBox.setIsDelete(0);
    //项目id 过滤
    electricBox.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    IPage<ElectricBox> electricBoxIPage = baseMapper.queryListByPage(page, electricBox);
    electricBoxIPage.getRecords().forEach(e ->{
      e.setQrCodeUrl(qrCodeUrl);
    });
    return electricBoxIPage;
  }

  /**
   * 验证重复
   */
  private void checkExist(ElectricBox electricBox) {
    QueryWrapper<ElectricBox> queryWrapper = new QueryWrapper<>();
    //设置判断重复条件
    queryWrapper.eq("code_",electricBox.getCode())
        .eq("is_delete_",0)
        .eq("tenant_id_",electricBox.getTenantId());
    //编辑的时候存在id
    Optional.ofNullable(electricBox.getId()).ifPresent(id -> queryWrapper.ne("id",electricBox.getId()));
    Integer integer = baseMapper.selectCount(queryWrapper);
    if (integer>0){
      throw new BusinessException("该配电箱已存在");
    }
  }

  @Override
  public void checkMonitorDevice(ElectricBox electricBox) {
    if(StringUtils.isNotBlank(electricBox.getMonitorDeviceCode())){
      QueryWrapper<ElectricBox> queryWrapper = new QueryWrapper<>();
      //设置判断重复条件
      queryWrapper.eq("monitor_device_code_",electricBox.getMonitorDeviceCode())
          .eq("is_delete_",0);
      List<ElectricBox> electricBoxes = baseMapper.selectList(queryWrapper);
      //如果存在多个，则报错
      if(CollectionUtil.isNotEmpty(electricBoxes) && electricBoxes.size()>1){
        List<String> codes = electricBoxes.stream().map(ElectricBox::getCode)
            .collect(Collectors.toList());
        throw new BusinessException("该电气火灾设备已经被绑定，绑定设备为"+codes);
      }else if(CollectionUtil.isNotEmpty(electricBoxes) && electricBoxes.size()==1){
        ElectricBox existOne = electricBoxes.get(0);
        if(!existOne.getCode().equals(electricBox.getCode())){
          throw new BusinessException("该电气火灾设备已经被绑定，绑定设备为"+existOne.getCode());
        }
      }
    }
  }

  /**
   * 查看当天的巡检记录
   * @param requestModel 1已巡检 0未巡检
   */
  @Override
  public IPage<ElectricBoxDTO> todayCheck(RequestModel<ElectricBoxDTO> requestModel) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    requestModel.getCustomQueryParams().setTenantId(tenantId);
    IPage<ElectricBoxDTO> records = baseMapper.todayCheck(requestModel.getPage(), requestModel.getCustomQueryParams());
    return records;
  }

  /**
   * 设置基本属性
   * @param electricBox
   */
  private void setBase(ElectricBox electricBox) {
    electricBox.setModifyTime(new Date());
    electricBox.setModifyId(linkappUserContextProducer.getCurrent().getId());
    //没有id就是新增,有就是编辑
    if (StringUtils.isBlank(electricBox.getId())){
      electricBox.setIsDelete(0);
      electricBox.setCreatorId(linkappUserContextProducer.getCurrent().getId());
      electricBox.setCreateTime(new Date());
      electricBox.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    }
  }

  @Override
  public List<ElectricBox> listUnChecked() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    Date start = calendar.getTime();
    return baseMapper.listUnChecked(start, new Date());
  }

  @Override
  public IPage<ElectricBox> listUnCheckedDetails(RequestModel<MessageCenter> electricBoxRequestModel) {
    Page page = electricBoxRequestModel.getPage();
    MessageCenter messageCenter = electricBoxRequestModel.getCustomQueryParams();
    Assert.notNull(messageCenter, "参数为空");
    Date endTime = messageCenter.getCreateTime();
    Assert.notNull(endTime, "创建时间参数为空");
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(endTime);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    Date start = calendar.getTime();

    LinkappUser user = linkappUserContextProducer.getNotNullCurrent();
    messageCenter.setTenantId(user.getTenantId());
    
    //影响了业务就直接去掉。不太清楚具体情况
    messageCenter.setOwnerId(String.valueOf(user.getId())); 
    messageCenter.setSelf(true);
    
    return baseMapper.listUnCheckedDetails(page, messageCenter, start, endTime);
  }

  @Override
  public List<Device> getMonitorDevice(String id) {
    //查询配置表中的配置
    Config config =configService.getOneByKey("DQHZ_DEVICE_TYPE_NAMES");
    if(config==null){
      return null;
    }
    String value = config.getValue();
    //暂时考虑可能将来会有多种类型，这里做个将来的扩展，用逗号隔开
    if(StringUtils.isNotBlank(value)){
      String[] split = value.split(",");
      //获取配置中的所有设备类型
      QueryWrapper<DeviceType> queryWrapper = new QueryWrapper();
      queryWrapper.in("name", Arrays.asList(split));
      List<DeviceType> deviceTypes = deviceTypeService.list(queryWrapper);
      if(CollectionUtil.isNotEmpty(deviceTypes)){
        //获取这个类型下的型号
        List<String> typeIds = deviceTypes.stream().map(DeviceType::getId)
            .collect(Collectors.toList());
        QueryWrapper<DeviceUnit> unitQueryWrapper = new QueryWrapper();
        unitQueryWrapper.in("device_type_id", typeIds);
        List<DeviceUnit> deviceUnits = deviceUnitService.list(unitQueryWrapper);
        if(CollectionUtil.isNotEmpty(deviceUnits)){
          List<String> deviceUnitIds = deviceUnits.stream().map(DeviceUnit::getId)
              .collect(Collectors.toList());

          List<Device> deviceList = deviceService
              .getMonitorDevice(linkappUserContextProducer.getNotNullCurrent().getTenantId(),
                  deviceUnitIds);

          //获取已经绑定的
          QueryWrapper<ElectricBox> boxQueryWrapper = new QueryWrapper<>();
          boxQueryWrapper.eq("tenant_id_",linkappUserContextProducer.getNotNullCurrent().getTenantId())
              .eq("is_delete_",0);
          List<ElectricBox> electricBoxes = baseMapper.selectList(boxQueryWrapper);
          //编辑时过滤本身数据
          if (StringUtils.isNotBlank(id)){
            electricBoxes.removeIf(e->id.equals(e.getId()));
          }
          List<String> codes = electricBoxes.stream().map(e -> e.getMonitorDeviceCode())
              .collect(Collectors.toList());

          //删除掉已经被选中的
          deviceList.removeIf(d-> codes.contains(d.getCode()));
          return deviceList;
        }
      }
    }
    return null;
  }
}
